from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
# from rest_framework_jwt.utils import jwt_decode_handler
import jwt,time
from jwt.exceptions import ExpiredSignatureError,DecodeError
from django.http import JsonResponse
from django.conf import settings
# from users.models import UserModel,PermissionTypeModel,PermissionModel

import re,redis,json,datetime

# 导入封装redis
from utils.redsi_con import redis_conn

# # 导入封装AES加密
# from utils.crypto_aes import Aes_Encrypt

# ip_blacklist = ["171.8.246.195","171.8.245.39","127.0.0.1"]

# 路由中间件 RBAC 鉴权中间件
class MyRBAC(MiddlewareMixin):
    # pv_key = settings.PV_KEY # PV
    # uv_key = settings.UV_KEY # UV
    # user_browse_key = "web_user_browse" # 用户访问时间
    # ip_black_list = [ i.decode() for i in redis_conn().smembers(settings.IP_BLACK_KEY)] # ip 黑名单
    # ouauth_url = settings.OUAUTH_URL
    # url_rbac = settings.URL_RBAC # 游客访问权限

    # 处理请求
    def process_request(self,request):
        try:
            x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')  # 判断是否使用代理
            if x_forwarded_for:
                ip = x_forwarded_for.split(',')[0]  # 使用代理获取真实的ip
            else:
                ip = request.META.get('REMOTE_ADDR')  # 未使用代理获取IP

            print("ip", ip,"访问时间：",datetime.datetime.now())

            # 拒绝黑名单
            # if ip in self.ip_black_list:
            #     return JsonResponse({"code": 205, "msg": "ip 禁止访问！"})


            key = "ip_%s"%ip
            num = redis_conn().get(key)
            if not num:
                redis_conn().set(key,0,ex=60)
            else:
                redis_conn().incr(key, 1) # 访问次数 + 1
                num = int(num.decode())
                print("访问次数:",num)
                if num > 100:
                    return JsonResponse({"code": 205, "msg": "访问过于频繁！"})

            path = request.path_info
            method = request.method.lower()  # GET = get

            if re.findall("sms_code|register|login", path, re.I):
                return None
            # if path == "/favicon.ico":
            #     return None

            # 获取用户访问地址，请求方法
            # path = request.path_info.lstrip('/')
            # # 解密路由
            # aes = Aes_Encrypt()
            # request_path = aes.decrypt(path)
            # if request_path == None:
            #     return JsonResponse({"code": 400, "msg": "非法访问"})
            # # /blogs/blogs/ 1656852742188
            # path = request_path.split()[0]  # 获取路由
            # url_time = request_path.split()[1]  # 获取时间戳
            #
            # # 校验请求是否过期
            # if int(url_time) < int(time.time()): # 请求过期
            #     return JsonResponse({"code": 404, "msg": "非法请求"})
            #
            # # 将解密后的路由返回request请求
            # request.path_info = path
            # path = path[1:] # /blogs/blogs/  去除前面/  结果 blogs/blogs/
            #
            # print("访问路由",method,request.path_info)
            #
            # # 统计 PV
            # # 日访问
            # if path != "favicon.ico":
            #     redis_conn().incr(self.pv_key)
            #
            #
            # token = request.headers.get("Authorization")
            # token_exp = False
            # token_auth = False
            # user_id = 0
            # username = "游客"
            token = request.headers.get("Authorization")
            try:
                payload = jwt.decode(token, key=settings.SECRET_KEY, algorithms='HS256')
                print("看看",payload)
                user_id = payload.get("user_id")
                shops_id = payload.get("shop_id")
            except ExpiredSignatureError:
                return JsonResponse({"code": 401, "msg": "token过期"})
            except DecodeError:
                return JsonResponse({"code": 402, "msg": "请重新登录"})
            request.session["user_id"] = user_id
            request.session["shops_id"] = shops_id
            print("访问用户",user_id,shops_id,path)
            # # 统计UV
            # if not re.findall("favicon.ico",path,re.I) :
            #     uv_data = "%s %s"%(user_id,username)
            #     redis_conn().sadd(self.uv_key, uv_data)
            #
            #  # 统计用户访问时间
            # if "get" == method and re.findall("^blogs/blogs/$",path,re.I) and user_id:
            #     uv_user = redis_conn().get("user_browse_%s" % user_id)
            #     if not uv_user:
            #         # 30分钟 统计一次用户访问
            #         redis_conn().set("user_browse_%s" % user_id, user_id, ex=60 * 30)
            #         # 日访问
            #         user_browse = "%s %s %s" % (ip,user_id, datetime.datetime.now())
            #         redis_conn().sadd(self.user_browse_key, user_browse)
            #
            # # 权限是否为游客路由
            # for i in self.url_rbac:
            #     url_method = i.split()[0]
            #     url_path = i.split()[1]
            #     # print("路由",url_method,url_path)
            #
            #     # 判断当前请求 是否允许
            #     if url_method == method and re.findall(url_path,path,re.I): # re.I 忽略大小写
            #         # print("放过")
            #         # 继续往后走
            #         return None
            #
            #
            # # print("用户登录，需验证token-")
            # # 校验token
            # if token_exp:
            #     return JsonResponse({"code": 401, "msg": "token过期"})
            # if token_auth:
            #     return JsonResponse({"code": 402, "msg": "请重新登录"})
            #
            # # 用户登录，权限校验
            # user = UserModel.objects.filter(id=user_id).first()
            # role = user.role.all()
            # user_rbac = []
            # for i in role: # 获取所有角色权限
            #     user_rbac += i.permissionmodel_set.all()
            # # print("获取权限————")
            # # print("获取权限",user_rbac)
            #
            # # 权限校验
            # for i in user_rbac:
            #     url_method = i.code_name.split()[0]
            #     url_path = i.code_name.split()[1]
            #     # print("路由",method,path,url_method,url_path)
            #
            #     # 判断当前请求 是否允许
            #     if url_method == method and re.findall(url_path, path, re.I):  # re.I 忽略大小写
            #         # 获取token user_id
            #         request.session["user_id"] = user_id
            #
            #         # 继续往后走
            #         # return JsonResponse({"code": 205, "msg": "无权限访问！"}, status=200)
            #         return None
            #
            # # request.session["user_id"] = user_id
            # # if not user.is_staff:
            # return JsonResponse({"code": 405, "msg": "无权限访问！"}, status=200)

        except Exception as e:
            print("请求中间件错误",e)
            return JsonResponse({"code": 500, "msg": "服务器错误！"}, status=200)



    # 在执行视图之前调用
    def process_view(self, request, view_func, view_args, view_kwargs):
        try:

            # path = request.path_info
            # method = request.method.lower()  # GET = get
            #
            # # 跳过第三方路由
            # for i in self.ouauth_url:
            #     url_method = i.split()[0]
            #     url_path = i.split()[1]
            #     if url_method == method and re.findall(url_path, path, re.I):
            #         return None
            #
            # get_data = request.GET.get("params")
            #
            # request_data = request.body
            # aes = Aes_Encrypt()
            # # print("get",get_data,request_data)
            # if get_data:
            #     data = aes.decrypt(get_data)
            #     if data == None:
            #         return JsonResponse({"code": 400, "msg": "非法访问"})
            #     request.GET = data
            # elif request_data:
            #     request_data = request_data.decode()
            #     data = aes.decrypt(request_data)
            #     if data == None:
            #         return JsonResponse({"code": 400, "msg": "非法访问"})
            #     request.GET = data

            return None
        except Exception as e:
            print("视图前中间件错误",e)
            return JsonResponse({"code": 500, "msg": "服务器错误！"}, status=200)

    # 如果响应的实例有render()
    # 方法，process_template_response()
    # 在视图刚好执行完毕之后被调用。
    # def process_template_response(self, request, response):
        # 这个方法必须返回一个实现了render方法的响应对象。

    # 在视图抛出异常时调用
    # def process_exception(self, request, exception):
    #     if isinstance(exception, ValueError):
    #         return HttpResponse("404")

    # 返回响应时调用
    def process_response(self, request, response):
        try:
            # 清空sessoin
            request.session.flush()

            # print('响应')
            # print("响应",response.data)
            # code = response.data.get("code")
            # if code != 200:
            #     return response
            # data = response.data
            # aes = Aes_Encrypt()
            # response.data = aes.encrypt(data)
            # response.content = json.dumps(response.data)

            # 重新渲染模板
            # response._is_rendered = False
            # response.render()
            return response
            # return HttpResponse(data)
        except Exception as e:
            # print("响应中间件错误，不加密",e)
            return response
            # return JsonResponse({"code": 500, "msg": "服务器错误！"}, status=200)
